package com.chufan.bcproj;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.hyperledger.fabric.protos.peer.Query.ChaincodeInfo;
import org.hyperledger.fabric.sdk.BlockEvent.TransactionEvent;
import org.hyperledger.fabric.sdk.BlockchainInfo;
import org.hyperledger.fabric.sdk.ChaincodeID;
import org.hyperledger.fabric.sdk.Channel;
import org.hyperledger.fabric.sdk.HFClient;
import org.hyperledger.fabric.sdk.Orderer;
import org.hyperledger.fabric.sdk.Peer;
import org.hyperledger.fabric.sdk.ProposalResponse;
import org.hyperledger.fabric.sdk.QueryByChaincodeRequest;
import org.hyperledger.fabric.sdk.TransactionProposalRequest;
import org.hyperledger.fabric.sdk.security.CryptoSuite;

import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.MessageOrBuilder;

public class App {
	public static void main(String[] args) throws Exception {
		System.out.println("counter app");

		// 创建User实例
		String keyFile = "C:\\Users\\Tim\\dev\\crypto-config\\peerOrganizations\\org1.example.com\\users\\User1@org1.example.com\\msp\\keystore\\4a5b28ceb90c36cc7fb064092f3d7194f10bea109406681dd7ecbff796a2adc8_sk";
		String certFile = "C:\\Users\\Tim\\dev\\crypto-config\\peerOrganizations\\org1.example.com\\users\\User1@org1.example.com\\msp\\signcerts\\User1@org1.example.com-cert.pem";
		LocalUser user = new LocalUser("User1", "Org1MSP", keyFile, certFile);

		// 创建HFClient实例
		HFClient client = HFClient.createNewInstance();
		client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
		client.setUserContext(user);

		// 创建通道实例
		Channel channel = client.newChannel("chufan");
		Properties props = new Properties();
		props.setProperty("pemFile",
				"C:\\Users\\Tim\\dev\\crypto-config\\peerOrganizations\\org1.example.com\\peers\\peer0.org1.example.com\\tls\\ca.crt");
		Peer peer = client.newPeer("peer1", "grpcs://peer0.org1.example.com:7051", props);
		channel.addPeer(peer);

		// add msp node
		props.clear();
		props.setProperty("pemFile",
				"C:\\Users\\Tim\\dev\\crypto-config\\peerOrganizations\\org2.example.com\\peers\\peer0.org2.example.com\\tls\\ca.crt");
		peer = client.newPeer("peer2", "grpcs://peer0.org2.example.com:9051", props);
		channel.addPeer(peer);

		props.clear();
		props.setProperty("pemFile",
				"C:\\Users\\Tim\\dev\\crypto-config\\ordererOrganizations\\example.com\\orderers\\orderer.example.com\\tls\\ca.crt");
		Orderer orderer = client.newOrderer("orderer1", "grpcs://orderer.example.com:7050", props);
		channel.addOrderer(orderer);

		channel.initialize();

		//Get blockchain height
	    BlockchainInfo bci = channel.queryBlockchainInfo(peer);
	    System.out.println("==========> Blockchain height:" + bci.getHeight());
	    //get instantiate chaicode info
	    List<ChaincodeInfo> instan = channel.queryInstantiatedChaincodes(peer);    
	    for(ChaincodeInfo cci : instan) {
	    	System.out.println("=======> InstantiatedChaincodes:" + cci.getPath() + " | " + cci.getName());
	    }
		// 查询链码
		QueryByChaincodeRequest req = client.newQueryProposalRequest();
		ChaincodeID cid = ChaincodeID.newBuilder().setName("mycc").build();
		req.setChaincodeID(cid);
		req.setFcn("query");
		req.setArgs(new String[] { "a" });
		ProposalResponse[] rsp = channel.queryByChaincode(req).toArray(new ProposalResponse[0]);
		System.out.format("rsp message A=> %s\n",
				rsp[0].getProposalResponse().getResponse().getPayload().toStringUtf8());
		QueryByChaincodeRequest req1 = client.newQueryProposalRequest();
//		ChaincodeID cid = ChaincodeID.newBuilder().setName("mycc").build();
		req1.setChaincodeID(cid);
		req1.setFcn("query");
		req1.setArgs(new String[] { "b" });
		rsp = channel.queryByChaincode(req1).toArray(new ProposalResponse[0]);
		System.out.format("rsp message B=> %s\n",
				rsp[0].getProposalResponse().getResponse().getPayload().toStringUtf8());

		// 提交链码交易
		TransactionProposalRequest req2 = client.newTransactionProposalRequest();
		req2.setChaincodeID(cid);
		req2.setProposalWaitTime(3000);
		req2.setUserContext(user);
		req2.setFcn("invoke");
		req2.setArgs(new String[] { "b", "a", "15" });
		Collection<ProposalResponse> rsp2 = channel.sendTransactionProposal(req2);
		TransactionEvent event = channel.sendTransaction(rsp2).get();
		System.out.format("txid: %s\n", event.getTransactionID());
		System.out.format("valid: %b\n", event.isValid());
		System.out.println("Event CHANNELID:"+event.getChannelId());
		Map<FieldDescriptor, Object> m =  event.getBlockEvent().getBlock().getAllFields();
		m.forEach((key,value)->{
			System.out.println( key.getFullName() + "<->" + value);
		});
	}
}
